#include "CircuitCreator.h"
#include "NodeFactory.h"

/*
===============================================================================
 Name        : CircuitCreator.cpp
 Author      : Bram en Paul
 Version     : 1.0
 Description : OOPatronen
===============================================================================
*/



/**
 * Constructor
 * 
 */
CircuitCreator::CircuitCreator()
{
	
}


/**
 * Maakt een nieuwe node aan op basis van het megegeven 'type'
 * 
 * @param string name Naam zoals deze opgeslagen zal worden. Deze naam moet later weer bekend zijn om het object terug te vinden
 * @param string type Type van de node (AND, OR etc.)
 * 
 * @return node Voor testdoeleinden kun je het gemaakte object terugvragen
 */
Node* CircuitCreator::newNode(string name, string type)
{
	//Nieuwe node maken op basis van het type
	Node* node = NodeFactory::createNode(type);
	//Niet bestaande node afvangen
	if (node == NULL) {
		return NULL;
	}
	//Anders toevoegen
	nodeNames.insert(std::pair<string, Node*>(name, node));

	//Als het een input is, moet ie ook in de inputlist komen!
	if (node->isInput() == 1)
		inputList.push_back(node);
	
	return node;
}


/**
 * Verbindt de meegegeven node met zijn outputs.
 * 
 * @param string name De naam die wordt gebruikt om de node terug te vinden
 * @param string connections[] De namen van de nodes waaraan de node die overeenkomt met 'name' vastgemaakt moet worden
 * @param int amountOfConnections Grootte van de array 'connections'
 */
void CircuitCreator::connectNode(string name, string connections[], int amountOfConnections)
{
	//Lege connections afvangen.
	if (connections->empty() == 1) {
		cout << "Internal error: Request to attach a Node to nothing. Why? \n";
		return;
	}

	//Hiermee vang ik het iteratorobject op. Die heeft velden zoals 'second' en 'first' die het gevonden paar voorstellen.
	std::map<string, Node*>::iterator temp = nodeNames.find(name);

	//Heeft het iteratorobject wel iets gevonden?
	if (temp == nodeNames.end())  {
		cout << "Warning: Unknown node '" << name << "'. Check circuit file. \n";
		return;
	}
	//Dit is het hoofdobject waaraan de connections[] vast gemaakt gaan worden
	Node* mainNode = temp->second;

	for (int i = 0; i < amountOfConnections; i++)
	{
		//Weer zo'n iterator.
		std::map<string, Node*>::iterator temp2;
		//Zoek heb object waaraan de mainNode gehangen moet worden
		temp2 = nodeNames.find(connections[i]);
		
		//Dit gebeurt als het object niet gevonden kan worden.
		if (temp2 == nodeNames.end())  {
			cout << "Warning: Unknown node '" << connections[i] << "'. Check circuit file. \n";
			break;
		}

		//Dit Nodeobject is gevonden.
		Node* foundNode = temp2->second;
		//Verbindt de output van mainNode aan foundNode.
		mainNode->addOutput(foundNode);
	}
}


/**
 * Zodra het hele circuit gebouwd is, moet deze functie aangeroepen worden om het 'signaal' te starten.
 */
void CircuitCreator::startCircuit()
{
	int maxSize = inputList.size();
	
	//Doorloop inputList (een lijst met alle inputobjecten)
	for (int i = 0; i < maxSize; i++)
	{
		//Een input-node start het circuit als het inputsignaal heeft gekregen.
		inputList[i] -> addInput(1);
	}
	
	//Valideren (zie documentatie bij methode)
	validateExecution();
}


/**
 * Deze methode controleert het circuit nadat het uitgevoerd is.
 * Als er nodes blijken te zijn die niet geheel naar behoren zijn uitgevoerd, wordt dit aan de gebruiker doorgegeven.
 * 
 * Note: Dit is een privémethode.
 */
void CircuitCreator::validateExecution()
{
	int counter = 0;

	//Deze iterator wordt in de for-loop gebruikt
	std::map<string, Node*>::iterator temp;

	//Doorloop nodeNames
	for (temp = nodeNames.begin(); temp != nodeNames.end(); temp++)
	{
		Node* element = temp->second;
		
		//Is alles bij deze node goed gegaan?
		char hasFinished = element->isFinished();
		
		//Zo nee, verhoog de counter
		if (hasFinished == 0) {
			counter++;
		}
	}

	//Als er 0 losse nodes waren hoeft er niks gezegd te worden.
	if (counter > 0) 
	{
		cout << "Warning: " << counter;

		if (counter == 1) {
			cout << " node did not execute successfully. \n";
		}
		else {
			cout << " nodes did not execute successfully. \n";
		}

		cout << "         Check circuit file for loops or unconnected pins.\n";
	}
}


/**
 * Met deze functie kan gekeken worden of een bepaalde node al in de nodeNames-lijst staat.
 * 
 * @return True/false
 */
bool CircuitCreator::nodeExists(string nodeName)
{
	//Hiermee vang ik het iteratorobject op. Die heeft velden zoals 'second' en 'first' die het gevonden paar voorstellen.
	std::map<string, Node*>::iterator temp = nodeNames.find(nodeName);

	//Heeft het iteratorobject iets gevonden?
	if (temp == nodeNames.end())  {
		return false;
	}
	else {
		return true;
	}
} 


/**
 * Destructor
 */
CircuitCreator::~CircuitCreator()
{
	
}
